package com.jsg.sl651.entity.frame.header;

import com.jsg.sl651.constant.FunctionCodeIdentifier;
import com.jsg.sl651.entity.station.AddressOfHydrologicalTelemetryStation;
import com.jsg.sl651.entity.station.RemoteTelemetryStationAddress;
import com.jsg.sl651.enums.CommunicationMessageType;
import com.jsg.sl651.enums.ControlCharacterDefinition;
import com.jsg.sl651.enums.FunctionCode;
import com.jsg.sl651.enums.LinkTransmissionMode;
import com.jsg.sl651.util.ByteUtil;
import com.jsg.sl651.util.SL651Tool;
import io.netty.buffer.ByteBuf;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;

@Data
@Accessors(chain = true)
public class MessageHeader implements Serializable {
    // 中心站地址
    private byte centralStationAddress;
    // 是不是水文站
    private boolean isHydroStation;
    // 遥测站地址
    private RemoteTelemetryStationAddress remoteTelemetryStationAddress;
    // 密码 两个字节的Hex
    private String password;
    // 功能码
    private Function function;
    // 报文上行标识及长度
    private IdentificationAndLength identificationAndLength;
    // 是不是M3分包发送
    private boolean isM3;
    // 链路传输模式(只能是1/2/4) 1:发送/无回答 2:发送/确认 4:查询/响应
    private LinkTransmissionMode linkTransmissionMode;
    // 分包信息（当为M3时才有效）
    private PacketInfo packetInfo;
    // 正文开始符号
    private ControlCharacterDefinition startOfTextSymbol;
    // 正文结束符
    private ControlCharacterDefinition endOfTextSymbol;


    public byte[] getBodyPassword(CommunicationMessageType type) {
        if (type == CommunicationMessageType.HEX) {
            return ByteUtil.toBytes(password);
        } else {
            return ByteUtil.stringToSimpleByteArray(password);
        }
    }


    /**
     * 获取可以放到报文里的中心站报文
     * @param type
     * @return
     */
    public byte[] getBodyCentralStationAddress(CommunicationMessageType type) {
        if (type == CommunicationMessageType.HEX) {
            return new byte[]{centralStationAddress};
        } else {
            return ByteUtil.stringToSimpleByteArray(ByteUtil.toHex(centralStationAddress));
        }
    }

    public static MessageHeader create(CommunicationMessageType type, ByteBuf data) {
        MessageHeader messageHeader = new MessageHeader();
        if (type == CommunicationMessageType.HEX) {
            parserHexImpl(messageHeader, data);
        } else {
            parserAsciiImpl(messageHeader, data);
        }
        return messageHeader;
    }


    private static void parserHexImpl(MessageHeader messageHeader, ByteBuf data) {
        // 中心站一个字节
        messageHeader.centralStationAddress = data.readByte();
        // 遥测站5个字节
        messageHeader.remoteTelemetryStationAddress = SL651Tool.remoteTelemetryStationAnalysis(ByteUtil.readBytes(data, 5));
        messageHeader.isHydroStation = messageHeader.remoteTelemetryStationAddress instanceof AddressOfHydrologicalTelemetryStation;
        messageHeader.password = ByteUtil.toHex(ByteUtil.readBytes(data, 2));
        messageHeader.function = FunctionCodeIdentifier.getFunction(data.readByte());
        messageHeader.identificationAndLength = new IdentificationAndLength(ByteUtil.readBytes(data, 2));
        initStartOfTextSymbol(messageHeader, data);
        if (messageHeader.isM3) {
            // 需要读取分包信息
            messageHeader.packetInfo = new PacketInfo(ByteUtil.readBytes(data,3));
        }
        // 读取正文结束符
        byte aByte = data.getByte(data.readerIndex() - 3);
        messageHeader.endOfTextSymbol = ControlCharacterDefinition.getControlCharacterDefinition(CommunicationMessageType.HEX, ByteUtil.toHex(aByte));
    }

    public static void parserAsciiImpl(MessageHeader messageHeader, ByteBuf data) {
        // 中心站一个字节 但是存储为2个字节的ASCII
        messageHeader.centralStationAddress = SL651Tool.mergeAsciiBytesToHexBytes(data);
        // 遥测站5个字节 存储为10个字节的ASCII
        messageHeader.remoteTelemetryStationAddress = SL651Tool.remoteTelemetryStationAnalysis(SL651Tool.mergeAsciiBytesToHexBytes(data,10));
        messageHeader.isHydroStation = messageHeader.remoteTelemetryStationAddress instanceof AddressOfHydrologicalTelemetryStation;
        messageHeader.password = ByteUtil.asciiHex(ByteUtil.readBytes(data,4));
        messageHeader.function = FunctionCodeIdentifier.getFunction(SL651Tool.mergeAsciiBytesToHexBytes(data));
        messageHeader.identificationAndLength = new IdentificationAndLength(SL651Tool.mergeAsciiBytesToHexBytes(data,4));
        initStartOfTextSymbol(messageHeader, data);
        if (messageHeader.isM3) {
            // 需要读取分包信息
            messageHeader.packetInfo = new PacketInfo(SL651Tool.mergeAsciiBytesToHexBytes(data,6));
        }
        // 读取正文结束符
        byte aByte = data.getByte(data.readerIndex() - 5);
        messageHeader.endOfTextSymbol = ControlCharacterDefinition.getControlCharacterDefinition(CommunicationMessageType.HEX, ByteUtil.toHex(aByte));
    }

    private static void initStartOfTextSymbol(MessageHeader messageHeader, ByteBuf data) {
        String startOfTextSymbol = ByteUtil.toHex(data.readByte());
        messageHeader.startOfTextSymbol = ControlCharacterDefinition.getControlCharacterDefinition(CommunicationMessageType.HEX, startOfTextSymbol);
        if (messageHeader.startOfTextSymbol == ControlCharacterDefinition.STX) {
            messageHeader.isM3 = false;
            messageHeader.linkTransmissionMode = LinkTransmissionMode.M1_M2_M4;
        } else if (messageHeader.startOfTextSymbol == ControlCharacterDefinition.SYN) {
            messageHeader.isM3 = true;
            messageHeader.linkTransmissionMode = LinkTransmissionMode.M3;
        } else {
            throw new RuntimeException("读取正文开始符失败");
        }
    }
}
